<?php
/**
 * Constants including files
 *
 * <p>Defines the default php file extension type, and the default
 * directory separator.
 */
define('JUNCTION_EXTENSION', '.php');
define('JUNCTION_UNDERSCORE', '_');
define('JUNCTION_EMPTY_STRING', "");

/**
 * Include the file for a given class only if the class 
 * definition is absent
 * 
 * <p>This function assumes that the class names follow the
 * PEAR naming conventions.
 *
 * @param String $classname
 * @return void
 */
function using($classname) {
	// PHP... why must you make this distinction?
	if (class_exists($classname) || interface_exists($classname))
		return;
	require(classtofile($classname));
}

/**
 * Return whether a given file exists
 * 
 * <p>This function assumes that the class names follow the
 * PEAR naming convetion.
 *
 * @param String $classname
 * @return boolean
 */
function exists($classname) {
	return file_exists(classtofile($classname));
}

/**
 * Include the specified file and ensure that it is only
 * included once.
 * 
 * <p>Note that the extension for the file should be omitted
 * and will be appended by the function.
 * <p>Use this function when you want to include a class but
 * it does not follow the PEAR naming convention.
 *
 * @param String $file fully qualified path to a file
 */
function get($file) {
	static $record = array();
	if (!$record[$file]) {
		require($file . JUNCTION_EXTENSION);
		$record[$file] = true;
	}
}

/**
 * Includes an entire package if each class 
 * definition is absent.
 * 
 * <p>This works similar to import in java.
 * 
 * @param string package
 */
function package($package)
{
	static $packages;
	if (!$packages[$package]) {
		$packages[$package] = true;
		$root = dirname(__FILE__);
		$path = str_replace("_", DIRECTORY_SEPARATOR, $package);
		
		$fullpath = $root . DIRECTORY_SEPARATOR . strtolower($path);
						
		if ($handle = opendir($fullpath)) {
			while (false !== ($file = readdir($handle))) {
				$file = $fullpath . DIRECTORY_SEPARATOR . $file;
				$classname = filetoclass($file);
				if(!is_dir($file) && !(class_exists($classname) || interface_exists($classname))) {
					require($file);
				}
			}
			closedir($handle);
		}
	}
}

/**
 * Take a class name and return the absolute path to the file containing it.
 * 
 * <p>This only works for classes following the PEAR naming convention.
 * 
 * @param string class name
 * @return string
 */
function classtofile($classname) {
	$root = dirname(__FILE__);
	$path = str_replace("_", DIRECTORY_SEPARATOR, $classname);
	
	return $root . DIRECTORY_SEPARATOR . strtolower(dirname($path)) . 
					DIRECTORY_SEPARATOR . basename($path) . JUNCTION_EXTENSION;
}

/**
 * Take a file name and return the class which resides in the file
 * 
 * <p>This only works for classes following the PEAR naming convention.
 * It will work for both files with an absolute path and those relative
 * to the root directory.
 */
function filetoclass($file) {
	$root = dirname(__FILE__);
	$file = str_replace($root, "", $file);
	$class = basename($file, JUNCTION_EXTENSION);
	$dir = trim(dirname($file), "/");
	$parts = explode(DIRECTORY_SEPARATOR, $dir);
	$classname = "";
	foreach ($parts as $part) {
		$classname .= ucfirst($part) . '_';
	}
	return $classname . $class;
}
?>